package router

import (
	"bytes"
	"gitee.com/Frank098/container-management/controller"
	"gitee.com/Frank098/container-management/docs"
	"gitee.com/Frank098/container-management/utils/log"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"github.com/swaggo/files"
	"github.com/swaggo/gin-swagger"
	"net/http"
	"net/http/httputil"
	"time"
)

//var cacheSctore = cache.New(10*time.Minute, 60*time.Minute)

type GinPanicWriter struct {
}

func (w GinPanicWriter) Write(p []byte) (n int, err error) {
	log.Error("gin panic recovered :", string(p))
	return 0, err
}

type bodyLogWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (w bodyLogWriter) Write(b []byte) (int, error) {
	return w.body.Write(b)
}

func Register() *gin.Engine {
	gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
		log.Infof("%-6s %-25s --> %s (%d handlers)", httpMethod, absolutePath, handlerName, nuHandlers)
	}
	r := gin.New()

	//用自己的日志库收集记录panic日志
	r.Use(gin.RecoveryWithWriter(&GinPanicWriter{}))

	//session组件
	//store := cookie.NewStore([]byte("secret"))
	//r.Use(sessions.Sessions("session", store))

	r.Use(controller.Logger())
	r.Use(cors.Default())
	r.Use(controller.TimeoutMiddleware(time.Minute * 5))

	//swagger文档托管
	var BasePath = "/api"
	docs.SwaggerInfo.Title = "Kubernetes集群应用管理平台API接口文档"
	docs.SwaggerInfo.Description = "对接鉴权功能尚未开发..."
	docs.SwaggerInfo.Version = "1.0"
	docs.SwaggerInfo.BasePath = BasePath
	docs.SwaggerInfo.Schemes = []string{"http", "https"}

	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	apiV1 := r.Group(BasePath,
		controller.CheckContentType,
	)

	nodes := controller.Node
	nodesGroup := apiV1.Group("/nodes")
	nodesGroup.GET("/info", nodes.GetNodeInfo)
	nodesGroup.GET("/all", nodes.GetNodeAll)

	namespaces := controller.Namespace
	namespacesGroup := apiV1.Group("/namespaces")
	namespacesGroup.GET("/info", namespaces.GetNamespaceInfo)
	namespacesGroup.GET("/list", namespaces.GetAllNamespace)
	namespacesGroup.DELETE("/del", namespaces.DeleteNamespace)
	namespacesGroup.DELETE("/create", namespaces.CreateNamespace)

	pod := controller.Pod
	podGroup := apiV1.Group("/pods")
	podGroup.GET("/info", pod.GetPodInfo)
	podGroup.DELETE("/delete", pod.DeletePod)
	podGroup.GET("/log", pod.PodLog)
	podGroup.GET("/all", pod.GetPodAllPerNp)
	podGroup.GET("/single", pod.GetPodSingleNp)
	podGroup.POST("/cmd", pod.PodCmdExec)
	podGroup.GET("/yaml", pod.GetPodYaml)
	podGroup.GET("/ssh", pod.PodSsh)

	deployment := controller.Deployment
	deploymentGroup := apiV1.Group("/deployments")
	deploymentGroup.GET("/info", deployment.GetDeploymentInfo)
	deploymentGroup.PUT("/scale", deployment.ScaleDeployment)
	deploymentGroup.DELETE("/delete", deployment.DeleteDeployment)
	deploymentGroup.PUT("/restart", deployment.RestartDeployment)
	deploymentGroup.GET("/all", deployment.GetDeployNumPerNp)
	deploymentGroup.GET("/Special", deployment.GetDeploySpecial)
	deploymentGroup.GET("/single", deployment.GetDeploySingleNp)
	deploymentGroup.POST("/create", deployment.CreateDeployment)
	deploymentGroup.GET("/yaml", deployment.GetDeployYaml)
	//deploymentGroup.PUT("/update", deployment.UpdateDeployment)
	/*
		daemonsets := controller.DaemonSet
		daemonsetsGroup := apiV1.Group("/daemonsets")
		daemonsetsGroup.GET("/info", daemonsets.GetDaemonSets)
		daemonsetsGroup.GET("/detail", daemonsets.GetDaemonSetDetail)
		daemonsetsGroup.DELETE("/del", daemonsets.DeleteDaemonSet)
		daemonsetsGroup.PUT("/update", daemonsets.UpdateDaemonSet)

		statefulsets := controller.StatefulSet
		statefulsetsGroup := apiV1.Group("/statefulsets")
		statefulsetsGroup.GET("/info", statefulsets.GetStatefulSets)
		statefulsetsGroup.GET("/detail", statefulsets.GetStatefulSetDetail)
		statefulsetsGroup.DELETE("/del", statefulsets.DeleteStatefulSet)
		statefulsetsGroup.PUT("/update", statefulsets.UpdateStatefulSet)

		pv := controller.Pv
		pvGroup := apiV1.Group("/pv")
		pvGroup.GET("/info", pv.GetPvs)
		pvGroup.GET("/detail", pv.GetPvDetail)

		svc := controller.Servicev1
		svcGroup := apiV1.Group("/svc")
		svcGroup.GET("/info", svc.GetServices)
		svcGroup.GET("/detail", svc.GetServiceDetail)
		svcGroup.DELETE("/del", svc.DeleteService)
		svcGroup.PUT("/update", svc.UpdateService)
		svcGroup.POST("/create", svc.CreateService)

		ingress := controller.Ingress
		ingressGroup := apiV1.Group("/ingress")
		ingressGroup.GET("/info", ingress.GetIngresses)
		ingressGroup.GET("/detail", ingress.GetIngressDetail)
		ingressGroup.DELETE("/del", ingress.DeleteIngress)
		ingressGroup.PUT("/update", ingress.UpdateIngress)
		ingressGroup.POST("/create", ingress.CreateIngress)

		pvc := controller.Pvc
		pvcGroup := apiV1.Group("/pvc")
		pvcGroup.GET("/api/k8s/pvcs", pvc.GetPvcs)
		pvcGroup.GET("/api/k8s/pvc/detail", pvc.GetPvcDetail)
		pvcGroup.DELETE("/api/k8s/pvc/del", pvc.DeletePvc)
		pvcGroup.PUT("/api/k8s/pvc/update", pvc.UpdatePvc)

	*/

	r.NoRoute(func(c *gin.Context) {
		proxy := httputil.ReverseProxy{
			Director: func(request *http.Request) {
				request.Header = c.Request.Header
				request.URL.Scheme = "https"
				request.URL.Host = "artifacthub.io"
				request.Host = "artifacthub.io"
			},
		}
		blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
		proxy.ServeHTTP(blw, c.Request)
		resDataString := string(blw.body.Bytes())
		c.Writer.Write([]byte(resDataString))
		return
	})
	return r
}
